<?xml version="1.0" encoding="UTF-8"?><d:tdl xmlns="http://www.w3.org/1999/xhtml" xmlns:b="http://www.backbase.com/2006/btl"   xmlns:c="http://www.backbase.com/2006/command" xmlns:d="http://www.backbase.com/2006/tdl" >
	<d:namespace name="http://www.backbase.com/2006/btl">
		<d:uses interface="iDataCommunicator" src="../../www.backbase.com.2006.btl/dataBinding/dataBinding.xml"/>
	</d:namespace>

	<d:namespace name="http://www.backbase.com/2007/jsf/client">
		<d:behavior name="jsfData" implements="b:iDataCommunicator">
			
			
			<d:resource type="text/javascript"><![CDATA[if (!bb.bjsf)
	bb.bjsf = {};

if (!bb.bjsf.dataBinding)
	bb.bjsf.dataBinding = {};

bb.bjsf.dataBinding.incomingData = function(oControl, oElement){
	if (!oControl)
		return;
	if (!oControl._jsf_updated){
		var aColumns = oControl.getProperty('columns');
		for (var i=0; aColumns.length > i; i++){
			aColumns[i].setProperty('fieldCreator', bb.bjsf.dataBinding.btlFieldCreator);
			aColumns[i].setProperty('fieldDestroyer', bb.bjsf.dataBinding.btlFieldDestroyer);
		}
		oControl._jsf_updated = true;
	}
	var oSource = oControl.getProperty('dataSource');
	if (oSource) {
		var oActionGroup = btl.dataSource.types.getType('jsf').unserialize(oElement, btl.dataSource.getDataField(oSource, '@rowIdx'), oSource);
		var aActions = oActionGroup.getActionList();
		for (var k = 0, len = aActions.length; k < len; k++) {
			var oAction = aActions[k];
			switch (oAction.type) {
				case 'read':
					if (oAction.hasAttribute('totalRecords')) {
						oControl.setProperty('indexes', []);
					} else if (bb.instanceOf(oControl, btl.namespaceURI, 'treeGridBase')){
						var aIndexes = oControl.getProperty('indexes'); //current list of indexes
						aNewIndexes = [];

						var sInsertPoint = null; //record id to insert after or before
						sInsertPoint = oAction.getAttribute('insertBefore');

						if (!sInsertPoint || !sInsertPoint.length){ //insert after
							sInsertPoint = oAction.getAttribute('insertAfter');
							for (var i = 0; aIndexes.length > i; i++)
								if (i && (aIndexes[i - 1] == sInsertPoint))
									break;
								else
									aNewIndexes[aNewIndexes.length] = aIndexes[i];
						} else { //insert before
							for (var i = 0; aIndexes.length > i; i++)
								if (aIndexes[i] == sInsertPoint)
									break;
								else
									aNewIndexes[aNewIndexes.length] = aIndexes[i];
						}
						if (sInsertPoint && sInsertPoint.length){
							var iTailStart = aNewIndexes.length;

							//make a list of records to insert
							var sParentId = ''; //top level
							sParentId = btl.dataSource.getValue(oSource, sInsertPoint, 'parent');
							var aRecords = oAction.records.getRecordList();
							for (var i = 0; i < aRecords.length; i++) {
								aNewIndexes[aNewIndexes.length] = aRecords[i].source.getAttribute('rowIdx');
							}

							if (aNewIndexes.length == iTailStart) { //there was no records inserted
								oEvent.initEvent('error', true, false);
								oEvent.message = "No records were found to insert at the specified place";
								oEvent.code = 0;
								oSource.dispatchEvent(oEvent);
								return;
							}

							//push the rest
							for (var i = iTailStart; aIndexes.length > i; i++)
								aNewIndexes[aNewIndexes.length] = aIndexes[i];
							oAction.setAttribute('indexes', aNewIndexes);
						}
					}
					var aRecordIds = oAction.records.getRecordIds();
					for (var i = 0; i < aRecordIds.length; i++){
						var oRec = oSource._.oRecords.getRecord(aRecordIds[i]);
						if (oRec)
							oRec.clearUpdates();
					}
					break;
				case 'delete':
					if (bb.instanceOf(oControl, btl.namespaceURI, 'treeGridBase')) {
						var aAllIndexes = [];

						var arr = oAction.hasAttribute('records') ? oAction.getAttribute('records') : [];
						if (arr.length){
							for (var i = 0, iMax = arr.length; iMax > i; i++){
								var recId = arr[i].replace(/(^\s+)|(\s+$)/g, '');

								if (recId){
									aAllIndexes[ aAllIndexes.length] = recId;
									var aList = btl.treeGrid.listChildren(oControl, recId);
									for (var j=0, jMax = aList.length; jMax > j; j++)
										aAllIndexes[ aAllIndexes.length] = aList[j];
								}
							}//for
							oAction.setAttribute('records', aAllIndexes);
						}
					}
			}//switch
		}//for
		oSource.acceptData(oActionGroup, null);
	}
}

bb.bjsf.dataBinding.btlFieldCreator = function jsf_btlFieldCreator(viewNode, controller, recordId, value){
	if (controller.getAttribute('renderMode') == 'html'){
		viewNode.innerHTML = value;
		return null;
	} else { //btl
		var sValue = '<?xml version="1.0"?><span xmlns="http://www.w3.org/1999/xhtml">'+ value +'</span>';
		var oXml = bb.xml.parse(sValue, true).documentElement;
		bb.construct(oXml);
		var oHost = bb.getControllerFromModel(oXml);
		bb.callMethod(controller, 'appendChild', [oHost]);
		return oHost;
	}
}
bb.bjsf.dataBinding.btlFieldUpdater = function jsf_btlFieldUpdater(viewNode, controller, object, recordId, value){
	if (controller.getAttribute('renderMode') == 'html'){
		viewNode.innerHTML = value;
		return null;
	} else { //btl
		var sValue = '<?xml version="1.0"?><span xmlns="http://www.w3.org/1999/xhtml">'+ value +'</span>';
		var oXml = bb.xml.parse(sValue, true).documentElement;
		bb.construct(oXml);
		var oHost = bb.getControllerFromModel(oXml);
		bb.callMethod(controller, 'appendChild', [oHost]);
		return oHost;
	}
}
bb.bjsf.dataBinding.btlFieldDestroyer = function jsf_btlFieldDestroyer(object){
	if (object){
		object.getProperty('parentNode').removeChild(object);
		bb.destruct(object);
	}
}

/**
 * XML type handler (application/xml)
 */
bb.bjsf.dataBinding.JSFTypeHandler = function JSFTypeHandler_constructor() {
}
bb.bjsf.dataBinding.JSFTypeHandler.prototype = new btl.dataBinding.XMLTypeHandler();

bb.bjsf.dataBinding.JSFTypeHandler.prototype.serialize = function JSFTypeHandler_serialize(data) {
	return data;
}

bb.bjsf.dataBinding.JSFTypeHandler.prototype.getValue = function JSFTypeHandler_getValue(oRecord, oDataField, bRaw) {
	if (oRecord) {
		var oNode = btl.dataBinding.XMLTypeHandler.prototype.getValue.call(this, oRecord, oDataField, true);
		if (bRaw)
			return oNode;
		return bb.bjsf.dataBinding.getChildWithClass(oNode, 'view');
	}
	return '';
}

bb.bjsf.dataBinding.JSFTypeHandler.prototype.setValue = function JSFTypeHandler_setValue() {
}


/**
 * JSF edit value formatter
 */
bb.bjsf.dataBinding.JSFEditFormatter = function JSFEditFormatter_constructor() {
	btl.dataBinding.Formatter.call(this);
}
bb.bjsf.dataBinding.JSFEditFormatter.prototype = new btl.dataBinding.Formatter();

bb.bjsf.dataBinding.JSFEditFormatter.prototype.raw = true;

bb.bjsf.dataBinding.JSFEditFormatter.prototype.format = function JSFEditFormatter_format(sFormattedValue, oValue) {
	return bb.bjsf.dataBinding.getChildWithClass(oValue, 'value');
}


/**
 * Returns the serialization of the child of the specified node that has the specified class name,
 * or, if no such child is present, the serialization of the node itself. Or, if the node is not
 * really a node (but say a string) the node itself, or the empty string if the node is null.
 * @param {Node} node The node.
 * @param {String} className The class name.
 * @return Serialized XML.
 * @type String
 */
bb.bjsf.dataBinding.getChildWithClass = function bb_bjsf_dataBinding_getChildWithClass(oNode, sClassName) {
	if (oNode && oNode.nodeType) {
		var oChild = oNode.firstChild;
		while (oChild) {
			if (oChild.nodeType == 1 && oChild.getAttribute('class') == sClassName)
				return bb.xml.serialize(oChild, true);
			oChild = oChild.nextSibling;
		}
		//if not found
		return bb.xml.serialize(oNode, true);
	}
	return oNode || '';
}
]]></d:resource>

			<d:attribute name="renderMode" default="btl">
				
			</d:attribute>

			<d:attribute name="dataType" default="jsf">
				
				<d:mapper type="text/javascript"><![CDATA[
					if (this._.jsf_constructed)
						btl.dataBinding.setType(this, value);
				]]></d:mapper>
			</d:attribute>

			<d:method name="sendRequest">
				<d:argument name="action"/>
				<d:argument name="observer"/>
				<d:body type="text/javascript"><![CDATA[
					if (!observer || !action)
						return;

					if (!observer._jsf_updated) {
						var aColumns = observer.getProperty('columns');
						for (var i = 0; aColumns.length > i; i++) {
							aColumns[i].setProperty('fieldCreator', bb.bjsf.dataBinding.btlFieldCreator);
							aColumns[i].setProperty('fieldDestroyer', bb.bjsf.dataBinding.btlFieldDestroyer);
						}
						observer._jsf_updated = true;

						var sName = '$' + this.modelNode.getAttribute('name').replace(/\:|-|;/g, '_');
						var oData = bb.evaluateSmart(sName, this.modelNode);
						bb.bjsf.dataBinding.incomingData(observer, oData);
					} else {
						var action = action;
						switch (action.type) {
						case 'sort':
							var sortField = action.hasAttribute('sortField') ? action.getAttribute('sortField') : '';
							var sortDirection = action.hasAttribute('sortDirection') ? action.getAttribute('sortDirection') : 'ascending';
							bb.bjsf.sync(observer, 'sort-column', 'column', sortField, 'direction', sortDirection);
							break;

						case 'update':
							if (action.records) {
								// observer.setProperty('indexes', []);
								var aIndex = observer.getProperty('indexes');
								var aRecordIds = action.records.getRecordIds();
								for (var j = 0; j < aRecordIds.length; j++) {
									var recId = aRecordIds[j];
									for (var i = 0; i < aIndex.length; i++) {
										if (aIndex[i] == recId) {
											aIndex.splice(i, 1);
											observer.setProperty('indexes', aIndex);
											break;
										}
									}
								}
								bb.bjsf.sync(observer, 'edit', 'rowIndex', recId);
							}
							break;

						case 'delete':
							break;

						case 'read':
							var bRequested = false;
							if (action.hasAttribute('select')) { //populate, only one condition is supported
								var hSelect = action.getAttribute('select');
								for (var sId in hSelect)
									if (!(hSelect[sId] instanceof Function) && (hSelect[sId] != '')) {
										bb.bjsf.sync(observer, 'populate', 'rowId', hSelect[sId]);
										bRequested = true;
										break;
									}
							}
							if (!bRequested) { //simple read
								var iPage = action.hasAttribute('page') ? action.getAttribute('page') : 1;
								bb.bjsf.sync(observer, 'select-page', 'page', iPage, 'populate', 'true');
							}
							break;
						}
					}

					//Continue with the queue
					btl.dataSource.requestQueueContinue(this);
				]]></d:body>
			</d:method>

			<d:handler event="DOMNodeInsertedIntoDocument" type="text/javascript"><![CDATA[
				btl.dataSource.types.addType('jsf', new bb.bjsf.dataBinding.JSFTypeHandler());

				//need to set listGridCol 'editFormat' attribute to 'jsfEditValue'
				btl.dataBinding.formatters.addFormatter('jsfEditValue', new bb.bjsf.dataBinding.JSFEditFormatter());

				this._.jsf_constructed = true;
				btl.dataBinding.setType(this, this.getAttribute('dataType'));
				this.setAttribute('identifier', '@rowIdx');
			]]></d:handler>
		</d:behavior>
	</d:namespace>
</d:tdl>